package com.sx.scheduler;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.sx.common.R;
import com.sx.config.YktConfig;
import com.sx.domain.dto.CheckInRspDTO;
import com.sx.domain.dto.GetLessonIdRspDTO;
import com.sx.domain.dto.OnLessonClassroomsRspDTO;
import com.sx.domain.dto.UserInfoRspDTO;
import com.sx.domain.vo.WebsocketReqVO;
import com.sx.holder.TokenHolder;
import com.sx.utils.DateUtils;
import com.sx.utils.EmailUtils;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.sx.constant.RequestPathConstant.*;

@Slf4j
@Component
public class ClassRoomScheduler {
    @Resource
    private YktConfig yktConfig;
    @Resource
    private EmailUtils emailUtils;
    private Map<String, String> headers = new HashMap<>(3);


    @PostConstruct
    public void init(){
        headers.put("Cookie", yktConfig.getCookie());
        headers.put("User-Agent", yktConfig.getUserAgent());
        headers.put("XTBZ", yktConfig.getXtbz());
        getUserId();
        monitorClassRooms();
    }

    public void getUserId(){
        HttpResponse httpResponse = HttpRequest
                .get(GET_USER_INFO_PATH)
                .headerMap(headers, true)
                .execute();
        if (!httpResponse.isOk()){
            log.error("请求失败,当前时间：{}",  LocalDateTime.now());
            return;
        }
        Type responseType = new TypeToken<R<UserInfoRspDTO>>() {
        }.getType();
        Gson gson = new Gson();
        R<UserInfoRspDTO> result = gson.fromJson(httpResponse.body(), responseType);
        if (result.getCode() == 0){
            TokenHolder.setToken("userId", result.getData().getId());
            log.info("获取用户ID成功，用户ID为：{}", result.getData().getId());
        }else {
            log.error("获取用户ID失败，错误信息为：{}", result.getMsg());
        }
    }



    /**
     * 每五分钟监测一次课堂情况
     */
    public void monitorClassRooms() {
        HttpResponse httpResponse = HttpRequest
                .get(ON_LESSON_PATH)
                .headerMap(headers, true)
                .execute();
        Gson gson = new Gson();
        if (!httpResponse.isOk()){
            log.error("请求失败,当前时间：{}",  LocalDateTime.now());
            return;
        }

        Type responseType = new TypeToken<R<OnLessonClassroomsRspDTO>>() {
        }.getType();
        R<OnLessonClassroomsRspDTO> result = gson.fromJson(httpResponse.body(), responseType);
        OnLessonClassroomsRspDTO onLessonClassroomsRspDTO = result.getData();
        List<OnLessonClassroomsRspDTO.OnLessonClassroomRspDTO> onLessonClassroomList =
                onLessonClassroomsRspDTO.getOnLessonClassroomList();
        List<OnLessonClassroomsRspDTO.UpcomingExam> upcomingExamList =
                onLessonClassroomsRspDTO.getUpcomingExamList();

        if (CollectionUtil.isNotEmpty(onLessonClassroomList)){
            OnLessonClassroomsRspDTO.OnLessonClassroomRspDTO onLessonClassroomRspDTO = onLessonClassroomList.get(0);
            StringBuilder message = new StringBuilder();
            System.out.println("即将开始课程："+onLessonClassroomRspDTO.getCourseName());
            message.append(onLessonClassroomRspDTO.getCourseName())
                    .append("课程即将开始，请注意查看!!!");
            String classroomId = onLessonClassroomRspDTO.getClassroomId();
            Boolean b = checkIn(getLessonId(classroomId));
            if (b) {
                message.append("已经顺利帮您签到！");
            }
            emailUtils.GetEmailCode(String.valueOf(message));
        }

        if (CollectionUtil.isNotEmpty(upcomingExamList)){
            StringBuilder message = new StringBuilder();
            System.out.println("考试了,当前时间"+LocalDateTime.now());
            message.append("您有")
                    .append(upcomingExamList.size())
                    .append("场考试即将开始，请注意查看!!!");
            upcomingExamList.forEach(u ->{
                LocalDateTime beginTimeStamp = DateUtils.toLocalDateTime(u.getStartTime());
                Long endTimeStamp = u.getEndTime();
                message.append("考试标题：").append(u.getTitle())
                        .append("，开始时间：").append(beginTimeStamp);
                if (endTimeStamp == 0){
                    message.append("，不限时").append("\n");
                }else {
                    LocalDateTime endTime = DateUtils.toLocalDateTime(endTimeStamp);
                    message.append("，结束时间：").append(endTime)
                            .append("\n");
                }
            });
            emailUtils.GetEmailCode(String.valueOf(message));
        }
    }

    public String getLessonId(String classroomId){
        Map<String,Object> params = new HashMap<>(5);
        params.put("actype",-1);
        params.put("page",0);
        params.put("offset",20);
        params.put("sort",-1);
        HttpResponse httpResponse = HttpRequest
                .get(GET_LESSON_ID_PATH+"/"+classroomId)
                .headerMap(headers, true)
                .form(params)
                .execute();
        Gson gson = new Gson();
        if (!httpResponse.isOk()){
            log.error("请求失败,当前时间：{}",  LocalDateTime.now());
            return "";
        }
        Type responseType = new TypeToken<R<GetLessonIdRspDTO>>() {
        }.getType();
        R<GetLessonIdRspDTO> result = gson.fromJson(httpResponse.body(), responseType);
        GetLessonIdRspDTO getLessonIdRspDTO = result.getData();
        return getLessonIdRspDTO.getActivities().get(0).getCoursewareId();
    }

    public Boolean checkIn(String lessonId){
        Map<String,Object> params = new HashMap<>(5);
        params.put("lessonId",lessonId);
        params.put("source",5);
        Gson gson = new Gson();
        String json = gson.toJson(params);
        HttpResponse httpResponse = HttpRequest.post(CHECK_IN_PATH)
                .headerMap(headers, true)
                .body(json)
                .execute();
        if (!httpResponse.isOk()){
            log.error("请求失败,当前时间：{}",  LocalDateTime.now());
            return false;
        }
        Type responseType = new TypeToken<R<CheckInRspDTO>>() {
        }.getType();
        R<CheckInRspDTO> result = gson.fromJson(httpResponse.body(), responseType);
        CheckInRspDTO checkInRspDTO = result.getData();
        TokenHolder.setToken("lessonId", checkInRspDTO.getLessonId());
        TokenHolder.setToken("lessonToken", checkInRspDTO.getLessonToken());
        listenClassroomEvent(checkInRspDTO.getLessonId(), checkInRspDTO.getLessonToken());
        return true;
    }


    public void listenClassroomEvent(String lessonId, String lessonToken){
        WebSocketClient wsc = null;
        try {
            wsc = new WebSocketClient(new URI("wss://www.yuketang.cn/wsapp/")) {
                @Override
                public void onOpen(ServerHandshake serverHandshake) {
                    // 在连接成功后发送消息
                    WebsocketReqVO websocketReqVO = new WebsocketReqVO();
                    websocketReqVO.setAuth(lessonToken);
                    websocketReqVO.setOp("hello");
                    websocketReqVO.setRole("student");
                    websocketReqVO.setUserid(TokenHolder.getToken("userId"));
                    websocketReqVO.setLessonid(lessonId);
                    String message = JSONObject.toJSONString(websocketReqVO);
                    send(message);
                }

                @Override
                public void onMessage(String s) {
                    JSONObject resultObject = JSONObject.parseObject(s);
                    String op = resultObject.getString("op");
                    if ("unlockproblem".equals(op)){
                        System.out.println("rainy,答题了!当前时间："+LocalDateTime.now());
                        emailUtils.GetEmailCode("雨课堂，答题了!");
                    }
                }

                @Override
                public void onClose(int i, String s, boolean b) {
                    // 执行重连
                    listenClassroomEvent(lessonId,  lessonToken);
                }

                @Override
                public void onError(Exception e) {
                    listenClassroomEvent(lessonId,  lessonToken);
                }
            };
            wsc.connect();
        }catch (URISyntaxException e){
            log.error("连接失败", e);
        }
    }
}
